/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package GameServer;

import ClientBL.Event;
import ClientBL.EventArrayResult;
import ClientBL.GameDetailsResult;
import ClientBL.GetActiveGamesResponse;
import ClientBL.GetWaitingGamesResponse;
import ClientBL.IDResult;
import ClientBL.MonopolyGame;
import ClientBL.MonopolyGamePortType;
import ClientBL.MonopolyResult;
import ClientBL.PlayerDetailsResult;
import Monopol.MonopolExceptions.MonopolErrors;
import Utils.GameDetails;
import Utils.LoadInfo;
import Utils.Utils;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 *
 * @author blecherl
 */
public class BackendService {

    private MonopolyGamePortType monopolyGamePortType;

    public BackendService() {
        monopolyGamePortType = new MonopolyGame().getMonopolyGameHttpSoap11Endpoint();
    }

     /**
     * Sets the Monopoly Game Port Type For Connecting the Server
     * @param serverName The Server Name to Connect to
     * @param serverPort The Server Port to Connect With
     */
    void setServerName(String serverName, Integer serverPort) {
	try {
	    URL url = new URL("http://" + serverName + ":" + serverPort + "/axis2/services/MonopolyGame?wsdl");
	    monopolyGamePortType = new MonopolyGame(url).getMonopolyGameHttpSoap11Endpoint();
	} catch (MalformedURLException ex) {
	    Logger.getLogger(BackendService.class.getName()).log(Level.SEVERE, null, ex);
	}
    }

    public String getGameBoardSchema(){
        return monopolyGamePortType.getGameBoardSchema().getReturn().getValue();
    }

    public String getGameBoardXML() {
        return monopolyGamePortType.getGameBoardXML().getReturn().getValue();
    }

    public GameDetails getGameDetails(String gameName){
        GameDetailsResult gameDetails = monopolyGamePortType.getGameDetails(gameName);
        return new GameDetails(gameName,
                gameDetails.getStatus().getValue(),
                gameDetails.getTotalHumanPlayers(),
                gameDetails.getTotalComputerPlayers(),
                gameDetails.getJoinedHumanPlayers(),
                gameDetails.isIsAutomaticDiceRoll()
                );
    }

    @SuppressWarnings("finally")
	public MonopolyResult startGame(String name, int humanPlayers, int computerPlayers, boolean useAutomaticDiceRollCheckBox) {
	MonopolyResult result =  null;
	try{
        result = monopolyGamePortType.startGame(name, humanPlayers, computerPlayers, useAutomaticDiceRollCheckBox);
	}
	catch(Exception e){
	    result = new MonopolyResult();
	    result.setError(true);
	    e.printStackTrace();
	}
	finally{
	    return result;
	}
    } 

    @SuppressWarnings("unchecked")
	public List<String> getWaitingGames() {
        GetWaitingGamesResponse result = monopolyGamePortType.getWaitingGames();
        return result != null ? result.getReturn() : Collections.EMPTY_LIST;
    }

    @SuppressWarnings("unchecked")
	public List<String> getActiveGames() {
        GetActiveGamesResponse result = monopolyGamePortType.getActiveGames();
        return result != null ? result.getReturn() : Collections.EMPTY_LIST;
    }

    public int joinGame (String gameName, String playerName) {
        IDResult result = monopolyGamePortType.joinGame(gameName, playerName);
        if (hasError(result)) {
            return -1;
        } else {
            return result.getResult();
        }
    }

    private boolean hasError(MonopolyResult monopolyResult) {
        if (monopolyResult == null || monopolyResult.isError()) {
            JOptionPane.showMessageDialog(null, monopolyResult.getErrorMessage().getValue(), "Server Communication Error", JOptionPane.ERROR_MESSAGE);
            return true;
        } else {
            return false;
        }
    }

    public List<LoadInfo> getPlayersDetails(String gameName) {
        List<LoadInfo> players = new LinkedList<LoadInfo>();
        PlayerDetailsResult result = monopolyGamePortType.getPlayersDetails(gameName);
        if (hasError(result)) {
            return Collections.emptyList();
        } else {
            for (int index=0 ; index < result.getNames().size() ; index++) {
                players.add(new LoadInfo(
                        result.getNames().get(index),
                        result.getMoney().get(index).doubleValue(),
                        result.getIsHumans().get(index),
                        result.getIsActive().get(index),
                        Utils.getRandomColor()));
                        
            }
            return players;
        }

    }

    public Boolean buy(Integer playerID, Integer eventID, Boolean toBuy) throws MonopolErrors {
	MonopolyResult buy = null;
	try {
	    buy = monopolyGamePortType.buy(playerID, eventID, toBuy);
	    return !buy.isError();
	} catch (Exception e) {
	    e.printStackTrace();
	    if (buy != null) {
		throw new MonopolErrors(buy.getErrorMessage().getValue());
	    }
	    else{
		// Construct an Error message
		throw new MonopolErrors("Could not Complete Buy Request, Unknown Error.");
	    }
	}
	
    }

    public Boolean resign(Integer playerID) throws MonopolErrors {
        MonopolyResult resign = null;
        try {
            resign = monopolyGamePortType.resign(playerID);
            return !resign.isError();
        } catch (Exception e) {
            e.printStackTrace();
            if (resign != null) {
                throw new MonopolErrors(resign.getErrorMessage().getValue());
            }
            return false;
        }
    }

    /**
     * Informs on a Manual Dice Roll to the Server
     * @param playerID The Player Unique ID who threw the Dices
     * @param eventID The Last Event ID For Prompting to Throw the Dices from the Server
     * @param dice1 The First Dice Result
     * @param dice2 The Second Dice Result
     * @return True/False if Operation Succeeded
     * @throws Monopol.MonopolExceptions.MonopolErrors
     */
    public Boolean setDiceRollresults(Integer playerID, Integer eventID, Integer dice1, Integer dice2) throws MonopolErrors{
	MonopolyResult setDiceRollResults = null;
	try{
	    // Send an Event to the Server
	    setDiceRollResults = monopolyGamePortType.setDiceRollResults(playerID, eventID, dice1, dice2);
	    // Return True if No Errors
	    return !setDiceRollResults.isError();
	} catch(Exception e){
	    e.printStackTrace();
	    // Check if we recieved an Error from the Server
	    if(setDiceRollResults != null){
		// Throw the Server Error
		throw new MonopolErrors(setDiceRollResults.getErrorMessage().getValue());
	    }else{
		// Construct an Error message
		throw new MonopolErrors("Could not Complete Setting the New Dices, Unknown Error.\nDices recieved were:" + dice1 + ", " + dice2);
	    }
	}
    }

    /**
     * Gets all the Events from the Last Event Forwards
     * @param lastEvent The Last Event Present at the Client
     * @return All the New Events from the Server
     */
    @SuppressWarnings("unchecked")
	public List<Event> getAllEvents(Integer lastEvent) throws MonopolErrors{
	try{
	EventArrayResult allEvents = monopolyGamePortType.getAllEvents(lastEvent);
        return allEvents != null ? allEvents.getResults() : Collections.EMPTY_LIST;
	}
        catch(Exception ex){
	    ex.printStackTrace();
	    String errMessage = "Could not Get Events From the Server.";
	    if(!ex.getMessage().isEmpty()){
		errMessage += "\nError was:\n\t" + ex.getMessage();
	    }
	    // Throw an error message
	    throw new MonopolErrors(errMessage);
	}
    }


}
